import { IMode } from "./IMode";
import { ArmatureController } from "../ArmatureController";
import { BoneView } from "../../views/BoneView";
import { Bone } from "../../models/Bone";
import { BoneController } from "../BoneController";
import { Container, Point } from "pixi.js";
import { emitter } from "../../../eventEmitter";
import { SelectedItemManager } from "../SelectedItemManager";

export class BoneCreaterController implements IMode {
    private _ctrl: ArmatureController;
    private _clickInsidePoint: Point | null = null;
    private _clickBone: BoneController | null = null;
    private _selectedItemManager: SelectedItemManager;

    private _preDragMovePoint = new Point();
    private _curDragMovePoint = new Point();
    private _tmpWorldPos = new Point();

    constructor(ctrl: ArmatureController) {
        this._ctrl = ctrl;
        this._selectedItemManager = ctrl.selectedItemManager;
        this._addBone(this._ctrl.view.parent, 100, 100);
    }

    private _addBone(stage: Container, x: number, y: number) {
        console.log("add bone pos", x, y);
        let boneView = new BoneView(stage, x, y);
        this._ctrl.view.addChild(boneView);

        let bone = new Bone();
        //this._ctrl.model.bone.push(bone);

        let boneController = new BoneController(boneView, bone);
        this._ctrl.boneControllers.unshift(boneController);
        //this._ctrl.boneControllers.set(boneController.name, boneController);

        if (this._ctrl.curBoneController) {
            this._ctrl.curBoneController.children.push(boneController);
            boneController.parent = this._ctrl.curBoneController;
            boneController.level = this._ctrl.curBoneController.level + 1;
            boneController.model.parent = boneController.parent.model.name;

            //create connection line
            let parent = boneController.parent;
            if (parent) {
                let beginPoint = (parent.view as BoneView).getTailPoint();
                let endPoint = boneController.view.position;
                let connectionLine = boneController.createConnectionLine(beginPoint, endPoint);
                this._ctrl.view.addChild(connectionLine);
            }
        }
        this._ctrl.model.addBone(bone, boneController.level);
        this._ctrl.curBoneController = boneController;

        //boneController.updateSelf();
        boneController.updateDisplay();
        //
        let armatureCtrl = this._ctrl;
        this._selectedItemManager.clearSelectedItems();
        this._selectedItemManager.addSelectItem(boneController);

        //
        if (boneController.parent) {
            let point = boneController.parent.view.toLocal( this._ctrl.view.toGlobal(new Point(x, y)));

            boneController.model.transform.x = point.x;
            boneController.model.transform.y = point.y;
        } else {
            boneController.model.transform.x = x;
            boneController.model.transform.y = y;
        }
        boneController.model.notifyUI();
    }

    public onDragStart(event: any): void {
        let armatureCtrl = this._ctrl;

        let point = new Point(event.global.x, event.global.y);
        this._preDragMovePoint.set(event.global.x, event.global.y);

        for (let bone of armatureCtrl.boneControllers.values()) {
            if (bone.isContainPoint(point)) {
                this._clickInsidePoint = point;
                this._clickBone = bone;
                if (this._selectedItemManager.hadSelectItem(bone)) {
                    console.log("aaaa");
                } else {
                    this._selectedItemManager.clearSelectedItems();
                    this._selectedItemManager.addSelectItem(bone);
                }

                return;
            }
        }

        this._clickInsidePoint = null;
        this._clickBone = null;
        this._tmpWorldPos.copyFrom(this._ctrl.view.toWorld(point.x, point.y));
        this._addBone(this._ctrl.view.parent, this._tmpWorldPos.x, this._tmpWorldPos.y);
    }

    public onDragMove(event: any): void {
        this._curDragMovePoint.set(event.global.x, event.global.y);
        this._tmpWorldPos.copyFrom(this._ctrl.view.toWorld(event.global));

        if (this._clickInsidePoint) {
            this._addBone(this._ctrl.view.parent, this._tmpWorldPos.x, this._tmpWorldPos.y);
            this._clickInsidePoint = null;
            this._clickBone = null;
            this._preDragMovePoint.copyFrom(this._curDragMovePoint);

            return;
        }

        if (this._ctrl.curBoneController) {
            //this._ctrl.curBoneController.updateTail(this._curDragMovePoint.x, this._curDragMovePoint.y);
            this._ctrl.curBoneController.updateTail(this._tmpWorldPos.x, this._tmpWorldPos.y);
            this._ctrl.curBoneController.model.notifyUI();
            //this._ctrl.curBoneController.updateLocalMatrix();
        }
        this._preDragMovePoint.copyFrom(this._curDragMovePoint);
    }

    public onDragMoveEnd(event: any): void {
        if (this._clickBone) {
            this._ctrl.curBoneController = this._clickBone;
            this._clickBone = null;
            return;
        }

        if (this._ctrl.curBoneController) {
            //this._ctrl.curBoneController.updateLocalMatrix();
            this._ctrl.curBoneController.updateMatrixByLocalTransform(this._ctrl.view.scaled);
            console.log("bone level creator", this._ctrl.curBoneController.level, this._ctrl.curBoneController.localMatrix);
        }
    }

    public onHover(event: any): void {
        let armatureCtrl = this._ctrl;

        for (const bone of armatureCtrl.boneControllers.values()) {
            let point = new Point(event.global.x, event.global.y);
            if (bone.isContainPoint(point)) {
                if (armatureCtrl.hoverItem == null || armatureCtrl.hoverItem !== bone) {
                    bone.hoverEnter();
                    if (armatureCtrl.hoverItem) {
                        armatureCtrl.hoverItem.hoverLeave();
                    }
                    armatureCtrl.hoverItem = bone;
                }
                return;
            }
        }

        if (armatureCtrl.hoverItem) {
            armatureCtrl.hoverItem.hoverLeave();
            armatureCtrl.hoverItem = null;
        }
    }

    public onEnter(): void {
        emitter.emit("changeCursor", "createBone");
        //change cur bone
        let firstSelectedBone = this._ctrl.selectedItemManager.getFirstSelectedBone();
        if (firstSelectedBone) {
            this._ctrl.selectedItemManager.clearSelectedItems();
            this._ctrl.selectedItemManager.addSelectItem(firstSelectedBone);
            this._ctrl.curBoneController = firstSelectedBone;
        } else {
            //let curBoneCtrl = this._ctrl.boneControllers[0];
            let curBoneCtrl = this._ctrl.getRootBoneCtrl();
            if (curBoneCtrl) {
                this._ctrl.selectedItemManager.addSelectItem(curBoneCtrl);
                this._ctrl.curBoneController = curBoneCtrl;
            }
        }
    }

    public onLeave(): void {

    }

    public updateOperateBar(visible: boolean): void {
        let firstSelectedBone = this._ctrl.selectedItemManager.getFirstSelectedBone();
        if (firstSelectedBone) {
            this._ctrl.selectedItemManager.clearSelectedItems();
            this._ctrl.selectedItemManager.addSelectItem(firstSelectedBone);
            this._ctrl.curBoneController = firstSelectedBone;
        }
    }
}